#include "Sessions.h"

int main(int argc, char *argv[])
{
    pcap_t *handle;			/* Session handle */
    char *dev = NULL;		/* The device to sniff on */
    char errbuf[PCAP_ERRBUF_SIZE];	/* Error string */
    struct bpf_program fp;		/* The compiled filter */
    char filter_exp[] = "ip";	/* The filter expression */
    bpf_u_int32 mask;		/* Our netmask */
    bpf_u_int32 net;		/* Our IP */
    struct pcap_pkthdr header;	/* The header that pcap gives us */
    const u_char *packet = 0;		/* The actual packet */

    char *srcFileName = NULL;
    char *uplinkFileName = NULL;
    char *downlinkFileName = NULL;

    u_char ip[4];
	u_char compIp[4];
    int packetNum = 0;

	if (strcmp(argv[1],"device") == 0) 
	{
	
		/* Print the list */
		pcap_if_t *alldevs;
		pcap_if_t *d;
		int inum;
		int i=0;

		if(pcap_findalldevs(&alldevs, errbuf) == -1)
		{
			fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
			exit(1);
		}
	
		/* Print the list */
		for(d=alldevs; d; d=d->next)
		{
			printf("%d. %s", ++i, d->name);
			if (d->description)
				printf(" (%s)\n", d->description);
			else
				printf(" (No description available)\n");
		}
	
		if(i==0)
		{
			printf("\nNo interfaces found! Make sure WinPcap is installed.\n");
			return -1;
		}
	
		printf("Enter the interface number (1-%d):",i);
		scanf("%d", &inum);
	
		if(inum < 1 || inum > i)
		{
			printf("\nInterface number out of range.\n");
			/* Free the device list */
			pcap_freealldevs(alldevs);
			return -1;
		}
	
		/* Jump to the selected adapter */
		for(d=alldevs, i=0; i< inum-1 ;d=d->next, i++);

        /* Open the session in promiscuous mode */
        handle = pcap_open_live(d->name, BUFSIZ, 1, 0, errbuf);
        if (handle == NULL)
        {
            fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
            return(2);
        }
	}

	if (strcmp(argv[1],"file") == 0) 
	{
		srcFileName = argv[2];
		if (srcFileName != NULL) 
		{
            handle = pcap_open_offline(srcFileName, NULL);
            if (handle == NULL) 
			{
                fprintf(stderr,"Unable to find input file.\n");
                return(2);
            }
        }
	}

	char * pchn;
	int l = 0;
	pchn = strtok (argv[3],".");
	while (pchn != NULL)
	{
		compIp[l] = atoi(pchn);
		l++;
		pchn = strtok (NULL, ".");
	}

	if (strcmp(argv[4],"dump") == 0) {
		char * pch;
        int l = 0;
        pch = strtok (argv[5],".");
        while (pch != NULL)
        {
            ip[l] = atoi(pch);
            l++;
            pch = strtok (NULL, ".");
        }

        packetNum = atoi(argv[6]);

        uplinkFileName = argv[7];
        downlinkFileName = argv[8];
	}
    

    /* Find the properties for the device */
    if(dev != NULL)
    {
        if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1)
        {
            fprintf(stderr, "Couldn't get netmask for device %s: %s\n", dev, errbuf);
            return(2);
        }
    }
    else net = 0xffffff;

    /* Compile and apply the filter */
    if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1)
    {
        fprintf(stderr, "Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
        return(2);
    }

    if (pcap_setfilter(handle, &fp) == -1)
    {
        fprintf(stderr, "Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
        return(2);
    }

    Sessions sess;

    while((packet = pcap_next(handle, &header)) != NULL)
    {
		if(strcmp(argv[4],"dump") == 0) {
			sess.AddPacket(packet, compIp, 0);

			if(sess.DumpSession(ip, packetNum, downlinkFileName)){
				sess.DumpReverseSession(ip, uplinkFileName);
				exit(0);
			}
		}

		if(strcmp(argv[4],"monitor") == 0) {
			sess.AddPacket(packet, compIp, 1);
		}
    }
	
	pcap_close(handle);
    return(0);
 }
